package com.wsh.security.service;

import com.wsh.scoket.WebSocketServer;
import com.wsh.security.config.SecurityProperties;
import com.wsh.security.security.vo.OnlineUser;
import com.wsh.sys.UserService;
import com.wsh.utils.EncryptUtils;
import com.wsh.utils.FileUtil;
import com.wsh.utils.RedisUtils;
import com.wsh.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

/**
 * @author Zheng Jie
 * @Date 2019年10月26日21:56:27
 */
@Service
@Slf4j
public class OnlineUserService {

    private final SecurityProperties properties;
    private RedisUtils redisUtils;

    public OnlineUserService(SecurityProperties properties, RedisUtils redisUtils) {
        this.properties = properties;
        this.redisUtils = redisUtils;
    }

    @Autowired
    private UserService userService;

    @Autowired
    private WebSocketServer webSocketServer;

    /**
     * 保存在线用户信息
     * @param userDetails /
     * @param token /
     * @param request /
     */
    public void save(UserDetails userDetails, String token, HttpServletRequest request){
        String job = "test";
        String ip = StringUtils.getIp(request);
        String browser = StringUtils.getBrowser(request);
        String address = StringUtils.getCityInfo(ip);
        OnlineUser onlineUser = null;
        String key = properties.getOnlineKey() + token;
        try {
            String username = userDetails.getUsername();
            onlineUser = new OnlineUser(username, userDetails.getUsername(), job, browser, ip, address, EncryptUtils.desEncrypt(token), new Date());
            // 更新用户登陆时间
            userService.updateUserState(username);
        } catch (Exception e) {
            log.error("保存用户信息异常 Exception={}", e.getMessage());
        }
        redisUtils.set(key, onlineUser, (properties.getTokenValidityInSeconds() / 1000));
    }

    /**
     * 查询全部数据，不分页
     *
     * @param filter /
     * @return /
     */
    public List<OnlineUser> getAll(String filter) {
        String onlineKey = properties.getOnlineKey() + "*";
        List<String> keys = redisUtils.scan(onlineKey);
        Collections.reverse(keys);
        List<OnlineUser> onlineUsers = new ArrayList<>();
        for (String key : keys) {
            OnlineUser onlineUser = (OnlineUser) redisUtils.get(key);
            if (StringUtils.isNotBlank(filter)) {
                if (onlineUser != null && onlineUser.toString().contains(filter)) {
                    onlineUsers.add(onlineUser);
                }
            } else {
                onlineUsers.add(onlineUser);
            }
        }
        onlineUsers.sort((o1, o2) -> o2.getLoginTime().compareTo(o1.getLoginTime()));
        return onlineUsers;
    }

    /**
     * 踢出用户
     * @param key /
     * @throws Exception /
     */
    public void kickOut(String key) throws Exception {
        key = properties.getOnlineKey() + EncryptUtils.desDecrypt(key);
        redisUtils.del(key);
    }

    /**
     * 退出登录
     * @param token /
     */
    public void logout(String token) {
        String key = properties.getOnlineKey() + token;
        redisUtils.del(key);
    }

    /**
     * 导出
     * @param all /
     * @param response /
     * @throws IOException /
     */
    public void download(List<OnlineUser> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (OnlineUser user : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("用户名", user.getUserName());
            map.put("岗位", user.getJob());
            map.put("登录IP", user.getIp());
            map.put("登录地点", user.getAddress());
            map.put("浏览器", user.getBrowser());
            map.put("登录日期", user.getLoginTime());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    /**
     * 查询用户
     * @param key /
     * @return /
     */
    public OnlineUser getOne(String key) {
        return (OnlineUser)redisUtils.get(key);
    }

    /**
     * 检测用户是否在之前已经登录，已经登录踢下线
     *
     * @param userName 用户名
     */
    public void checkLoginOnUser(String userName, String igoreToken) {
        List<OnlineUser> onlineUsers = getAll(userName);
        if (onlineUsers == null || onlineUsers.isEmpty()) {
            return;
        }
        for (OnlineUser onlineUser : onlineUsers) {
            if (StringUtils.isNotBlank(userName) && userName.equals(onlineUser.getUserName())) {
                // 通过webScoket发送需要踢出的用户token
                List<String> scan = redisUtils.scan("logout*");
                if (scan != null && !scan.isEmpty()) {
                    scan.stream().forEach(key -> {
                        webSocketServer.sendInfo("LOGOUT", key);
                        webSocketServer.onClose();
                    });
                }
            }
        }
    }
}